package com.cynteka.cyfoman.core.collection.scxml;

import com.cynteka.cyfoman.core.collection.CollectionRegistry;
import com.cynteka.cyfoman.core.scxml.SCXMLHelper;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.commons.scxml.SCXMLExecutor;
import org.apache.commons.scxml.Status;
import org.apache.commons.scxml.TriggerEvent;
import org.apache.commons.scxml.env.jexl.JexlContext;
import org.apache.commons.scxml.env.jexl.JexlEvaluator;
import org.apache.commons.scxml.model.SCXML;
import org.apache.commons.scxml.model.State;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * User: Sergey
 * Date: 09.08.11
 * Time: 15:08
 */
public class SCXMLCommand implements Command, BeanFactoryAware {
    public static final String COMMAND = "triggerCommand";
    public static final String COLLECTION_ID_PARAM = "collectionId";
    public static final String OBJECT_PARAM = "objectParam";
    public static final String TRIGGER_EVENT_PARAM = "triggerEvent";
    public static final String SET_STATE_TRIGGER_EVENT = "set-state";

    private CollectionRegistry collectionRegistry;
    private BeanFactory beanFactory;

    @Override
    public boolean execute(Context context) throws Exception {
        String collectionId = String.valueOf(context.get(COLLECTION_ID_PARAM));
        String sTriggerEvent = String.valueOf(context.get(TRIGGER_EVENT_PARAM));
        Object value = context.get(OBJECT_PARAM);

        SCXML stateMachine = collectionRegistry.getStateMachine(collectionId);
        JexlEvaluator jexlEvaluator = new JexlEvaluator();
        Map map = new HashMap();
        map.put("this", value);
        if(value instanceof Map) {
            // TODO check it
            map = (Map) value;
        }
        JexlContext jexlContext = new JexlContext(map);
        SCXMLExecutor executor = SCXMLHelper.getExecutor(stateMachine, jexlContext, jexlEvaluator);

        TriggerEvent setStatetriggerEvent = new TriggerEvent(SET_STATE_TRIGGER_EVENT, TriggerEvent.SIGNAL_EVENT);
        executor.triggerEvent(setStatetriggerEvent);

        Status status = executor.getCurrentStatus();
        System.out.println("After set state : ");
        printStates(status.getStates());

        TriggerEvent triggerEvent = new TriggerEvent(sTriggerEvent, TriggerEvent.SIGNAL_EVENT);
        executor.triggerEvent(triggerEvent);

        status = executor.getCurrentStatus();
        System.out.println("After " + sTriggerEvent);
        printStates(status.getStates());

        return false;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    public CollectionRegistry getCollectionRegistry() {
        return collectionRegistry;
    }

    public void setCollectionRegistry(CollectionRegistry collectionRegistry) {
        this.collectionRegistry = collectionRegistry;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }


    // TODO remove it
    private static void printStates(Set states) {
        System.out.print("[ ");
        for (Object oState : states) {
            State state = (State) oState;
            System.out.print(state.getId() + ", ");
        }
        System.out.println("]");
    }
}
